package com.easy.query.solon.web.encrypt;

import com.easy.query.core.basic.extension.encryption.EncryptionStrategy;
import com.easy.query.core.logging.Log;
import com.easy.query.core.logging.LogFactory;
import com.easy.query.core.util.EasyClassUtil;
import com.easy.query.core.util.EasyCollectionUtil;
import com.easy.query.core.util.EasyStringUtil;
import com.easy.query.solon.web.SM4Util;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * create time 2023/8/13 21:51
 * 文件说明
 *
 * @author xuejiaming
 */
public class JavaSM4EncryptionStrategy implements EncryptionStrategy {
    private static final Log log = LogFactory.getLog(JavaSM4EncryptionStrategy.class);
    private static final String key="1234567890123456";
    @Override
    public Object encrypt(Class<?> entityClass, String propertyName, Object plaintext) {

        if (plaintext == null) {
            return null;
        }
        try {
            return doEncrypt(plaintext);
        }catch (Exception exception){
            log.error(EasyClassUtil.getInstanceSimpleName(this)+" "+ EasyClassUtil.getSimpleName(entityClass)+"."+ "."+propertyName+" decrypt error:" + plaintext, exception);
            throw exception;
        }
    }

    protected Object doEncrypt(Object plaintext){
        String plaintextString = plaintext.toString();
        //4表示多少单位长度为一组,1表示非中文的情况下1个字符为一个单位长度,2表示一个中文字符为2个单位长度
        List<String> stringCharSegments = EasyStringUtil.getStringCharSegments(plaintextString, 4,1,2);
        //符合要求譬如最少4个非中文字符或者2个中文字的情况下,可以选择抛错重写或者直接加密对应的值
        if (EasyCollectionUtil.isEmpty(stringCharSegments)) {
            stringCharSegments.add(plaintextString);
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (String stringCharSegment : stringCharSegments) {
            String str= SM4Util.encrypt(stringCharSegment,key, StandardCharsets.UTF_8);
            stringBuilder.append(str);
        }
        return stringBuilder.toString();
    }

    @Override
    public Object decrypt(Class<?> entityClass,String propertyName,Object ciphertext) {
        try {
            return doDecrypt(entityClass,propertyName,ciphertext);
        } catch (Exception exception) {
            log.error(EasyClassUtil.getInstanceSimpleName(this)+" "+ EasyClassUtil.getSimpleName(entityClass)+"."+ "."+propertyName+" decrypt error:" + ciphertext, exception);
            throw exception;
        }
    }

    private Object doDecrypt(Class<?> entityClass,String propertyName,Object ciphertext) {
        if (ciphertext == null) {
            return null;
        }
        String ciphertextString = ciphertext.toString();
        if (ciphertextString.length() % 24 != 0) {
                throw new IllegalArgumentException(EasyClassUtil.getSimpleName(entityClass)+"."+propertyName+" decrypt cant decode base64:" + ciphertext);
        }

        List<String> segments = EasyStringUtil.splitString(ciphertextString, 24);

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < segments.size(); i++) {
            String str=SM4Util.decrypt(segments.get(i),key,StandardCharsets.UTF_8);
            boolean last = i == (segments.size() - 1);
            if (last) {
                stringBuilder.append(str);
            } else {
                stringBuilder.append(str.charAt(0));
            }
        }
        return stringBuilder.toString();
    }
}
